<?php

if (!class_exists('Uap_Woo')) :



class Uap_Woo extends Referral_Main{

	private $source_type = 'woo';

	private static $checkout_referrals_select_settings = array();

	protected static $coupon_code = '';



	public function __construct(){

		/*

		 * @param none

		 * @return none

		 */

		/// THE HOOKS



		//add_action('woocommerce_checkout_order_processed', array($this, 'create_referral')); /// <8.4

		// version >=8.4

		add_action('woocommerce_checkout_update_order_meta', array($this, 'create_referral'));



		/*

		* Fires before an order is processed by the Checkout Block/Store API.

		* This is similar to existing core hook woocommerce_checkout_order_processed.

		*/

		add_action('woocommerce_store_api_checkout_order_processed', array($this, 'create_referral_for_blocks'));



		add_action('woocommerce_order_status_completed', array($this, 'make_referral_verified'));

		add_action('wc-on-hold_to_trash', array($this, 'make_referral_refuse'));

		add_action('wc-processing_to_trash', array($this, 'make_referral_refuse'));

		add_action('wc-completed_to_trash', array($this, 'make_referral_refuse'));



		add_action( 'woocommerce_order_status_on-hold_to_processing', [$this, 'make_referral_refuse'] );



		add_action( 'woocommerce_order_status_changed', [ $this, 'change_status' ], 999, 4 );



		/// CHECKOUT REFERRALS SELECT

		add_action('woocommerce_after_order_notes', array($this, 'insert_affiliate_select'));

		add_action('woocommerce_checkout_process', array( $this, 'checking_affiliate_select'));



		//// SUBSCRIPTION

		add_action( 'init', array( $this, 'registerSubscriptionHooks' ) );

		/*

		add_action('woocommerce_customer_changed_subscription_to_active', array($this, 'make_wcs_referral_verified'), 999, 2);

		add_action('woocommerce_customer_changed_subscription_to_cancelled', array($this, 'make_wcs_referral_refuse'), 999, 2);

		*/

		add_filter('wcs_new_order_created', array($this, 'create_referral_and_return_renewal_order'), 999, 3);

	}



	public function registerSubscriptionHooks()

	{

			if ( !class_exists( 'WC_Subscriptions' ) || !isset(\WC_Subscriptions::$version) ){

					return;

			}



			if ( version_compare( \WC_Subscriptions::$version, '2.0', '<=') ){

					// >= 2.0

					add_action('woocommerce_customer_changed_subscription_to_active', array($this, 'make_wcs_referral_verified'), 999, 2);

					add_action('woocommerce_customer_changed_subscription_to_cancelled', array($this, 'make_wcs_referral_refuse'), 999, 2);

			} else {

					add_action('woocommerce_customer_changed_subscription_to_active', array($this, 'make_wcs_new_version_referral_verified'), 999, 1 );

					add_action('woocommerce_customer_changed_subscription_to_cancelled', array($this, 'make_wcs_new_version_referral_refuse'), 999, 1 );

			}



	}





	public function create_referral($order_id=0){

		/*

		 * @param int (order id)

		 * @return none

		 */

		if (empty($order_id)){

			return; // out

		}

		if (is_object($order_id)){

			$order_id = (isset($order_id->ID)) ? $order_id->ID : 0;

		}



		$order = new WC_Order($order_id);

		self::$user_id = (int)$order->get_user_id();



		if (empty(self::$affiliate_id)){

			/// let's check the coupon...

			$this->check_coupon($order);

		}



		$this->set_affiliate_id();



		///CHECKOUT REFERRAL SELECT

		$this->check_for_selected_affiliate();

		///CHECKOUT REFERRAL SELECT



		if ($this->valid_referral()){

			// it's valid



			/// tax & shipping settings

			global $indeed_db;

			$temp_data = $indeed_db->return_settings_from_wp_option('general-settings');

			$exclude_shipping = (empty($temp_data['uap_exclude_shipping'])) ? FALSE : TRUE;

			$exclude_tax = (empty($temp_data['uap_exclude_tax'])) ? FALSE : TRUE;



			/// calculate the amount object

			require_once UAP_PATH . 'public/Affiliate_Referral_Amount.class.php';

			$do_math = new Affiliate_Referral_Amount(self::$affiliate_id, $this->source_type, self::$special_payment_type, self::$coupon_code);



			if (!empty(self::$coupon_code)){

				$temp_coupon_data = $indeed_db->get_coupon_data(self::$coupon_code);

				if ($temp_coupon_data['amount_type']=='flat'){

					$run_foreach_line_once = TRUE;

				}

			}



			$items = $order->get_items();



			$shipping = $order->get_total_shipping();

			if ($shipping){

				$shipping_per_item = $shipping / count($items);

			} else {

				$shipping_per_item = 0;

			}

			$sum = 0;

			$product_price_sum = 0;

			$products_arr = [];

			foreach ($items as $item){ /// foreach in lines



				$variableProductId = isset( $item['variation_id'] ) ? $item['variation_id'] : false;



				// since version 8.6

				// excluded cat

				if ( $this->productCatIsExcluded( $item['product_id'] ) ){

						continue;

				}

				// excluded product

				if ( $this->isProductExcluded( $item['product_id'] ) ){

						continue;

				}

				// excluded variable product

				if ( $variableProductId !== false && $this->isVariableProductExcluded( $variableProductId ) ){

						continue;

				}

				// end of 8.6



				$products_arr[] = $item['product_id'];



				///base price

				$product_price = round($item['line_total'], 3);



				///add shipping if it's case

				if (!empty($shipping_per_item) && !$exclude_shipping){

					$product_price += round($shipping_per_item, 3);

				}



				/// add taxes if it's case

				if (!empty($item['line_tax']) && !$exclude_tax){

					$product_price += round($item['line_tax'], 3);

				}



				$product_price_sum += $product_price;



				/// get amount

				$do_math->setVariableProductId( $variableProductId );

				$temp_amount = $do_math->get_result( $product_price, $item['product_id'] );// input price, product id



				$sum += $temp_amount;



				if (!empty($run_foreach_line_once)){

					/// user for coupon flat amount!

					break;

				}

			}

			if (!empty($products_arr)){

				$product_list = implode(',', $products_arr);

			} else {

				$product_list = '';

			}



			// since version 8.6

			if ( $product_list === '' ){

					// no product -> out

					return false;

			}

			// end of since version 8.6



			$wooCurrency = $order->get_currency();

			$wooTotal = $order->get_total();

			if ( class_exists( 'WOOCS' ) && method_exists( $order, 'get_order_currency' ) ) {

					$wooCurrency = $order->get_order_currency();

			    global $WOOCS;

			    if ( isset( $WOOCS->default_currency ) && $wooCurrency != $WOOCS->default_currency ) {

			        $currencies = $WOOCS->get_currencies();

			        $sum = $WOOCS->back_convert($sum, $currencies[$wooCurrency]['rate'] );

			    }

			}

			$sum = apply_filters( 'uap_public_filter_on_referral_insert_amount_value', $sum, $wooCurrency );



			$description = esc_html__('WooCommerce Sale', 'uap');

			if(isset($wooTotal) && !empty($wooTotal)){

				$description = esc_html__('Order Amount: ', 'uap').'<strong>'.wc_price( $wooTotal ).'</strong>';

			}

			$args = array(

							'refferal_wp_uid' => self::$user_id,

							'campaign' => self::$campaign,

							'affiliate_id' => self::$affiliate_id,

							'visit_id' => self::$visit_id,

							'description' => $description,

							'source' => $this->source_type,

							'reference' => $order_id,

							'reference_details' => $product_list,

							'amount' => $sum,

							'currency' => self::$currency,

							'product_price' => $product_price_sum,

			);

			$this->save_referral_unverified($args);



		}

	}



	public function make_referral_verified($order_id=0){

		/*

		 * @param int

		 * @return none

		 */

		if ($order_id){

			$this->referral_verified($order_id, $this->source_type);

		}

	}



	public function make_referral_refuse($order_id=0){

		/*

		 * @param int

		 * @return none

		 */

		if ($order_id){

			if (is_object($order_id)){

				$order_id = (isset($order_id->ID)) ? $order_id->ID : 0;

			}

			$this->referral_refuse($order_id, $this->source_type);

		}

	}



	private function check_coupon($order_object){

		/*

		 * check if coupon has a affiliate on it

		 * @param object

		 * @return none

		 */

		 if ($order_object){



			 $coupons_arr = $order_object->get_coupon_codes();

			 if (!empty($coupons_arr)){

			 	global $indeed_db;

			 	foreach ($coupons_arr as $coupon){

			 		$affiliate = $indeed_db->get_affiliate_for_coupon_code($coupon);

					if ($affiliate){

						self::$affiliate_id = $affiliate;

						self::$special_payment_type = 'coupon';

						self::$coupon_code = $coupon;

					}

			 	}

			 }

		 }

	}



	//////////////// CHECKOUT REFERRAL SELECT



	public function check_for_selected_affiliate(){

		/*

		 * @param none

		 * @return none

		 */

		 global $indeed_db;

		 if (empty(self::$checkout_referrals_select_settings)){

		 	self::$checkout_referrals_select_settings = $indeed_db->return_settings_from_wp_option('checkout_select_referral');

		 }

		 if (self::$checkout_referrals_select_settings['uap_checkout_select_referral_enable']){

		 	if (!empty($_POST['uap_affiliate_username'])){

		 		self::$affiliate_id = sanitize_text_field($_POST['uap_affiliate_username']);

		 	} else if (!empty($_POST['uap_affiliate_username_text'])){

				$_POST['uap_affiliate_username_text'] = sanitize_text_field( $_POST['uap_affiliate_username_text'] );

		 		$temp = $indeed_db->get_affiliate_id_by_username($_POST['uap_affiliate_username_text']);

				if ($temp){

					self::$affiliate_id = $temp;

				}

		 	}

		 }

	}



	public function insert_affiliate_select(){

		/*

		 * @param none

		 * @return none

		 */

		 global $indeed_db;

		 if (empty(self::$checkout_referrals_select_settings)){

		 	self::$checkout_referrals_select_settings = $settings = $indeed_db->return_settings_from_wp_option('checkout_select_referral');

		 }

		 /// check it's enable

		 if (self::$checkout_referrals_select_settings['uap_checkout_select_referral_enable']){

		 	$this->set_affiliate_id();

		 	if (self::$affiliate_id && !self::$checkout_referrals_select_settings['uap_checkout_select_referral_rewrite']){

		 		return; /// OUT

		 	}

			$who = self::$checkout_referrals_select_settings['uap_checkout_select_affiliate_list'];

			$type = self::$checkout_referrals_select_settings['uap_checkout_select_referral_name'];

			$data['affiliates'] = $indeed_db->get_affiliates_for_checkout_select($who, $type);

			$data['require'] = (self::$checkout_referrals_select_settings['uap_checkout_select_referral_require']) ? '<abbr class="required" title="required">*</abbr>' : '';

			$data['class'] = 'form-row form-row';

			if ($data['require']){

				$data['class'] .= ' validate-required';

			}

			$data['select_class'] = '';

			$data['input_class'] = '';

			$data['require_on_input'] = '';

			require_once UAP_PATH . 'public/views/checkout_referral_select.php';

		 }

	}



	public function checking_affiliate_select(){

		/*

		 * @param none

		 * @return none

		 */

		 global $indeed_db;

		 if (empty(self::$checkout_referrals_select_settings)){

		 	self::$checkout_referrals_select_settings = $indeed_db->return_settings_from_wp_option('checkout_select_referral');

		 }

		 if (self::$checkout_referrals_select_settings['uap_checkout_select_referral_enable'] && self::$checkout_referrals_select_settings['uap_checkout_select_referral_require']){

		 	if (isset($_POST['uap_affiliate_username']) && $_POST['uap_affiliate_username']==''){

		 		$error = TRUE;

		 	} else if (isset($_POST['uap_affiliate_username_text']) && $_POST['uap_affiliate_username_text']==''){

		 		$error = TRUE;

		 	}

			 if (!empty($error)){

				 wc_add_notice(__('Please complete all required fields!', 'uap'), 'error');

			 }

		 }

	}



	//// Woo Blocks

	public function create_referral_for_blocks($new_order){

		if (isset($new_order->id)){

			$this->create_referral($new_order->get_id());

		}

	}



	//// WCS

	public function create_referral_and_return_renewal_order($new_order, $subscription, $type){

		if (isset($new_order->id)){

			$this->create_referral($new_order->id);

		}

		return $new_order;

	}



	public function make_wcs_referral_verified($new_status, $subscription){

		$this->make_referral_verified($subscription);

	}



	public function make_wcs_referral_refuse($new_status, $subscription){

		$this->make_referral_refuse($subscription);

	}



	public function make_wcs_new_version_referral_verified( $subscription = null )

	{

		$this->make_referral_verified($subscription);

	}



	public function make_wcs_new_version_referral_refuse( $subscription = null )

	{

		$this->make_referral_refuse($subscription);

	}



	/*

	 * 0 - REFUSE

	 * 1 - UNVERIFIED

	 * 2 - VERIFIED

	 */

	 public function change_status( $order_id=0, $status_transition_from = '', $status_transition_to = '', $that = '' )

	 {

		 	global $indeed_db;

	 		$referral_id = $indeed_db->get_referral_id_for_reference( $order_id, $this->source_type );

			switch ( $status_transition_to ){

					case 'cancelled':

						$status = 0;

						break;

					case 'on-hold':

						$status = 1;

						break;

					case 'pending':

						$status = 1;

						break;

					case 'processing':

						$status = 1;

						break;

					case 'refunded':

						// since version 8.6

						$makeRefuseOnRefunded = get_option( 'uap_reject_refund_referrals', 1 );

						if ( ((int)$makeRefuseOnRefunded) === 0 ){

								return;

						}

						// end of 8.6

						$status = 0;

						break;

					case 'failed':

						$status = 0;

						break;

			}

	 		if ( $referral_id && isset( $status ) ){

	 				$indeed_db->change_referral_status( $referral_id, $status );

	 		}

			if( $referral_id && isset( $status ) && $status == 0){

				$new_description = esc_html__(' - Order Refunded', 'uap');

				$indeed_db->change_referral_description($referral_id, $new_description, TRUE);

			}

	 }



	 /**

	  * since version 8.6 .

	  * @param int

		* @return bool

		*/

	 private function productCatIsExcluded( $productId=0 )

	 {

		 	 if ( $productId === 0 ){

				 	return false;

			 }

			 $terms = wc_get_product_term_ids( $productId, 'product_cat' );

			 if ( !$terms ){

			     return false;

			 }

			 foreach ( $terms as $termId ){

			     $maybeHide = get_term_meta( $termId, 'uap_excluded', true );

					 if ( (int)$maybeHide === 1 ){

						 	return true;

					 }

			 }

			 return false;

	 }



	 /**

	  * since version 8.6 .

	  * @param int

		* @return bool

		*/

	 private function isProductExcluded( $productId=0 )

	 {

			 if ( $productId === 0 ){

						return false;

			 }

			 $maybeHide = get_post_meta( $productId, 'uap-woo-excluded-prod', true );

			 if ( (int)$maybeHide === 1 ){

				 	return true;

			 }

			 return false;

	 }



	 /**

		* since version 8.6 .

		* @param int

		* @return bool

		*/

	 private function isVariableProductExcluded( $productId=0 )

	 {

			 if ( $productId === 0 ){

						return false;

			 }

			 $maybeHide = get_post_meta( $productId, 'uap-woo-excluded-variable_prod', true );

			 if ( (int)$maybeHide === 1 ){

					return true;

			 }

			 return false;

	 }



}



endif;

